/*
This is part of Screenbar, which is based in part on the Litestep
shell source code.

Copyright (C) 2008-2009 Jim Babcock
Copyright (C) 1997-2009 The LiteStep Development Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#pragma once

void warn(const char *warning);
void warnOnce(const char *warning);
void fatal(const char *error);

HWND getDesktopWindow();
Point getCursorPos();

string retprintf(const char *fmt, ...);
void tokenizeString(const string &str, vector<string> &result, const char *separators);
const char *skipwhitespace(const char *pos);
vector<string> separateArgs(const char *args);
string to_lower(string str);
string getWindowsErr();
UINT64 getSystemTime();
UINT64 Time64fromFileTime(FILETIME fileTime);

class BackBuffer
{
public:
	BackBuffer(int width, int height);
	~BackBuffer();
	void *getBits();
	HDC getDC();
	
protected:
	HDC hdc;
	void *bits;
	HBITMAP oldBmp;
	HBITMAP bmp;
};

enum Direction
{
	directionUnspecified = 0,
	directionUp,
	directionRight,
	directionDown,
	directionLeft,
};
Direction parseDirection(string direction);

struct Point
{
	inline Point() {}
	inline Point(int x, int y)
		:x(x), y(y) {}
	inline Point(const POINT pt)
		:x(pt.x), y(pt.y) {}
	inline operator POINT() const {
		POINT ret = {x,y};
		return ret;
	}
	inline string toString() const {
		return retprintf("(%i,%i)", x, y);
	}
	
	inline bool operator==(const Point &rhs) const
		{ return x==rhs.x && y==rhs.y; }
	inline bool operator!=(const Point &rhs) const
		{ return x!=rhs.x || y!=rhs.y; }
	inline Point operator+(const Point &rhs) const
		{ return Point(x+rhs.x, y+rhs.y); }
	inline Point operator-(const Point &rhs) const
		{ return Point(x-rhs.x, y-rhs.y); }
	inline void operator+=(const Point &rhs)
		{ x+=rhs.x; y+=rhs.y; }
	inline void operator-=(const Point &rhs)
		{ x-=rhs.x; y-=rhs.y; }
	
	int x, y;
};

struct Rect
{
	inline Rect() {left=top=width=height=0;}
	inline Rect(int left, int top, int width, int height)
		:left(left), top(top), width(width), height(height) {}
	inline Rect(const RECT &rect)
		:left(rect.left), top(rect.top), width(rect.right-rect.left), height(rect.bottom-rect.top) {}
	
	inline int getRight() const { return left+width; }
	inline int getBottom() const { return top+height; }
	inline Point getSize() const { return Point(width, height); }
	
	inline bool operator==(const Rect &rhs) const {
		return left==rhs.left && top==rhs.top && width==rhs.width && height==rhs.height;
	}
	inline bool operator!=(const Rect &rhs) const {
		return left!=rhs.left || top!=rhs.top || width!=rhs.width || height!=rhs.height;
	}
	
	inline operator RECT() const {
		RECT ret;
			ret.left = left;
			ret.top = top;
			ret.right = left+width;
			ret.bottom = top+height;
		return ret;
	}
	
	inline Point topLeft() const
		{ return Point(left, top); }
	
	inline bool containsPoint(int x, int y) const
	{
		return x>=left && x<(left+width) && y>=top && y<(top+height);
	}
	
	inline bool overlaps(const Rect &rhs) const
	{
		return left<=(rhs.left+rhs.width) && top<=(rhs.top+rhs.height)
		    && (left+width)>=rhs.left && (top+height)>=rhs.top;
	}
	
	inline Rect intersect(const Rect &rhs)
	{
		int left = max(this->left, rhs.left);
		int right = min(getRight(), rhs.getRight());
		int top = max(this->top, rhs.top);
		int bottom = min(getBottom(), rhs.getBottom());
		return Rect(left, top, right-left, bottom-top);
	}
	
	inline string toString() const {
		return retprintf("(l=%i, t=%i, w=%i, h=%i)", left, top, width, height);
	}
	
	int left, top, width, height;
};

/// Set dest=source, and set changeFlag=true if they were different
template<class T>
void updateAndFlag(T source, T& dest, bool &changeFlag)
{
	if(source != dest) {
		dest = source;
		changeFlag = true;
	}
}

enum Alignment
{
	alignCenter,
	alignLeft,
	alignRight,
	alignTop,
	alignBottom,
};
Alignment parseAlign(const string &str);

static const int mouseNumButtons = 3;
enum MouseButton {
	mouseLeft=0,
	mouseRight,
	mouseMiddle,
};
enum MouseAction {
	mouseMove = 0,
	mouseDown,
	mouseUp,
};
